Skip to main content

Coinpath for UTXO Networks

UTXOs (Unspent Transaction Outputs) are the basic unit of value on UTXO-based blockchains. Each UTXO represents a discrete amount that can be consumed as an input to a new transaction. Coinpath supports all major UTXO networks, including Bitcoin, Litecoin, Dogecoin, Bitcoin Cash, Zcash, and Dash.

How the Algorithm Works

Unlike EVM chains where balances change in-place, UTXO transactions consume one or more inputs and create one or more outputs. The challenge is: when a transaction has multiple inputs from different addresses, how much of each output should be attributed to each input?

Coinpath uses a proportional input-output amount attribution formula. Each output's amount is split across the inputs in proportion to their share of the total input value.

Worked Example

Consider a transaction with two inputs and three outputs:

Inputs:
Address A: 1 BTC
Address B: 2 BTC
─────────────────
Total: 3 BTC

Outputs:
Address C: 0.5 BTC
Address D: 2.0 BTC
Address B: 0.49 BTC (change)
─────────────────────
Total: 2.99 BTC (0.01 BTC fee)

Proportional attribution:

Address A contributed 1/3 of the total input, Address B contributed 2/3. So each output is attributed proportionally:

OutputTotalFrom A (1/3)From B (2/3)
Address C: 0.5 BTC0.50.167 BTC0.333 BTC
Address D: 2.0 BTC2.00.667 BTC1.333 BTC
Address B: 0.49 BTC (change)0.490.163 BTC0.327 BTC

Change Outputs

In UTXO mode, change outputs are treated as separate outputs and attributed like any other output. This is important because change goes back to one of the input addresses, and you may need to distinguish it from genuine transfers when analyzing fund flows. (In account-based / EVM mode, change is not a concept and is ignored.)

Example Query — Bitcoin Outbound Coinpath

Track where BTC moved from an address over 2 hops:

Open this query on IDE

{
bitcoin(network: bitcoin) {
outbound: coinpath(
initialAddress: { is: "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S" }
currency: { is: "BTC" }
depth: { lteq: 2 }
options: {
seed: 110
asc: "depth"
desc: "amount"
limitBy: { each: "depth", limit: 10 }
}
) {
sender {
address
annotation
}
receiver {
address
annotation
}
amount
currency {
symbol
}
depth
count
}
}
}